import math
class COPRAS:
    def __init__(self, DecisionMatrix, weight,q):
        self.DecisionMatrix = DecisionMatrix
        self.weight = weight
        self.type =[0,0]+[1 for i in range(len(self.DecisionMatrix[0])-2)]
        self.q=q
        self.row = len(self.DecisionMatrix)
        self.column = len(self.DecisionMatrix[0])

    def NormalizeDecisionMatrix(self):
        '''
        归一化矩阵
        :return: 返回归一化结果
        '''
        NomalizedMatrix = [[0 for i in range(0, self.column)] for j in range(0, self.row)]
        q=self.q

        sumValues = [([0, 0], [1, 1]) for i in range(self.column)]
        for j in range(self.column):
           matrix = [X[j] for X in self.DecisionMatrix]
           for i in range(self.row):
               sumValues[j] = ([(sumValues[j][0][0] ** q + matrix[i][0][0] ** q -
                                 (sumValues[j][0][0] ** q) * (matrix[i][0][0] ** q)) ** (1 / q),
                                (sumValues[j][0][1] ** q + matrix[i][0][1] ** q -
                                 (sumValues[j][0][1] ** q) * (matrix[i][0][1] ** q)) ** (1 / q)],
                               [(sumValues[j][1][0]) * (matrix[i][1][0]), (sumValues[j][1][1]) * (matrix[i][1][1])])
        for j in range(self.column):
            for i in range(self.row):
                NomalizedMatrix[i][j]=([(self.DecisionMatrix[i][j][0][0]**q+sumValues[j][1][0]**q
                                         -(self.DecisionMatrix[i][j][0][0]**q)*(sumValues[j][1][0]**q))**(1/q),
                                        (self.DecisionMatrix[i][j][0][1] ** q + sumValues[j][1][1] ** q
                                         - (self.DecisionMatrix[i][j][0][1] ** q) * (sumValues[j][1][1] ** q))**(1/q)],
                                       [self.DecisionMatrix[i][j][1][0]*(sumValues[j][0][0]),
                                        (self.DecisionMatrix[i][j][1][1])*(sumValues[j][0][1])])

        return NomalizedMatrix

    def getWeightedNormalizedDecision(self):
        q=self.q
        Nomalized=self.NormalizeDecisionMatrix()
        WeightedNomalizedMatrix = [[0 for i in range(0, self.column)] for j in range(0, self.row)]
        for i in range(self.row):
            for j in range(self.column):
                WeightedNomalizedMatrix[i][j]=([(1-(1-(Nomalized[i][j][0][0])**q)**(self.weight[j]))**(1/q),
                                                (1-(1-Nomalized[i][j][0][1]**q)**self.weight[j])**(1/q)],
                                               [(Nomalized[i][j][1][0])**(self.weight[j]),(Nomalized[i][j][1][1])**(self.weight[j])])

        return WeightedNomalizedMatrix

    def getMinMax(self):
        q=self.q
        WeightedNormalized=self.getWeightedNormalizedDecision()
        positive = [([0, 0], [1, 1]) for i in range(self.row)]
        negative = [([0, 0], [1, 1]) for i in range(self.row)]
        for i in range(self.row):
            for j in range(self.column):
                if(self.type[j]==1):
                    positive[i]=([(positive[i][0][0] ** q + WeightedNormalized[i][j][0][0] ** q -
                                 (positive[i][0][0] ** q) * (WeightedNormalized[i][j][0][0] ** q)) ** (1 / q),
                                (positive[i][0][1] ** q + WeightedNormalized[i][j][0][1] ** q -
                                 (positive[i][0][1] ** q) * (WeightedNormalized[i][j][0][1] ** q)) ** (1 / q)],
                               [(positive[i][1][0]) * (WeightedNormalized[i][j][1][0]), (positive[i][1][1]) * (WeightedNormalized[i][j][1][1])])
                else:
                    negative[i] = ([(negative[i][0][0] ** q + WeightedNormalized[i][j][0][0] ** q -
                                     (negative[i][0][0] ** q) * (WeightedNormalized[i][j][0][0] ** q)) ** (1 / q),
                                    (negative[i][0][1] ** q + WeightedNormalized[i][j][0][1] ** q -
                                     (negative[i][0][1] ** q) * (WeightedNormalized[i][j][0][1] ** q)) ** (1 / q)],
                                   [(negative[i][1][0]) * (WeightedNormalized[i][j][1][0]),
                                    (negative[i][1][1]) * (WeightedNormalized[i][j][1][1])])

        return positive,negative

    def getNegativeSum(self):
        q=self.q
        positive, negative=self.getMinMax()
        NegativeSum=[0, 0], [1, 1]
        for i in range(self.row):
            NegativeSum= ([(NegativeSum[0][0] ** q + negative[i][0][0] ** q -
                             (NegativeSum[0][0] ** q) * (negative[i][0][0] ** q)) ** (1 / q),
                            (NegativeSum[0][1] ** q + negative[i][0][1] ** q -
                             (NegativeSum[0][1] ** q) * (negative[i][0][1] ** q)) ** (1 / q)],
                           [(NegativeSum[1][0]) * (negative[i][1][0]),
                            (NegativeSum[1][1]) * (negative[i][1][1])])

        return NegativeSum

    def getReverseNegative(self):
        q = self.q
        positive, negative = self.getMinMax()
        c=([1,1],[0,0])
        negative2=[]
        for i in range(self.row):
            negative2.append(([c[0][0]**q+negative[i][1][0]**q-(c[0][0]**q)*(negative[i][1][0]**q),
                          c[0][1]**q+negative[i][1][1]**q-(c[0][1]**q)*(negative[i][1][1]**q)],
                         [c[1][0]*negative[i][0][0],c[1][1]*negative[i][0][1]]))


        ReverseNegativeSum = [0, 0], [1, 1]
        for i in range(self.row):
            ReverseNegativeSum= ([(ReverseNegativeSum[0][0] ** q + negative[i][0][0] ** q -
                             (ReverseNegativeSum[0][0] ** q) * (negative[i][0][0] ** q)) ** (1 / q),
                            (ReverseNegativeSum[0][1] ** q + negative[i][0][1] ** q -
                             (ReverseNegativeSum[0][1] ** q) * (negative[i][0][1] ** q)) ** (1 / q)],
                           [(ReverseNegativeSum[1][0]) * (negative[i][1][0]),
                            (ReverseNegativeSum[1][1]) * (negative[i][1][1])])

        return ReverseNegativeSum

    def getDiverse(self):
        q=self.q
        NegativeSum=self.getNegativeSum()
        NegativeReverseSum=self.getReverseNegative()
        positive,negative=self.getMinMax()
        Snegative=[]
        for i in range(self.row):
            a=([negative[i][0][0]*NegativeReverseSum[0][0],negative[i][0][1]*NegativeReverseSum[0][1]],
                [(negative[i][1][0]**q+NegativeReverseSum[1][0]**q-(negative[i][1][0]**q)*(NegativeReverseSum[1][0]**q))**(1/q),
            (negative[i][1][1] ** q+NegativeReverseSum[1][1]**q-(negative[i][1][1] ** q)*(NegativeReverseSum[1][1]**q))**(1/q)],
               )

            b=([(NegativeSum[0][0]**q+a[1][0]**q-(NegativeSum[0][0]**q)*(a[1][0]**q))**(1/q),
                (NegativeSum[0][1]**q+a[1][1]**q-(NegativeSum[0][1]**q)*(a[1][1]**q))**(1/q)],
            [NegativeSum[1][0]*a[0][0],NegativeSum[1][1]*a[0][1]])
            Snegative.append(b)
        return Snegative

    def getQ(self):
        q=self.q
        Q=[]
        positive, negative = self.getMinMax()
        b=self.getDiverse()
        for i in range(self.row):
            Q.append(([(positive[i][0][0]**q+b[i][0][0]**q-(positive[i][0][0]**q)*(b[i][0][0]**q))**(1/q),
                      (positive[i][0][1]**q+b[i][0][1]**q-(positive[i][0][1]**q)*(b[i][0][1]**q))**(1/q)],
                     [positive[i][1][0]*b[i][1][0],positive[i][1][0]*b[i][1][0]]))
        return Q

    def score(self,IVq, q):
        a1 = (IVq[0][0] ** q + IVq[0][1] ** q + ((IVq[0][1] + IVq[0][0]) / 2) ** q) / 3
        b1 = (IVq[1][0] ** q + IVq[1][1] ** q + ((IVq[1][1] + IVq[1][0]) / 2) ** q) / 3
        a = IVq[0][0]
        b = IVq[0][1]
        c = IVq[1][0]
        d = IVq[1][1]
        return (1 / 3) * (a1 - b1 + (1 / 2) * (a ** q - c ** q + b ** q - d ** q) - math.cos(
            ((IVq[0][0] + IVq[0][1]) / 2) * (3.1415 / 2)) + math.cos((IVq[1][0] - IVq[1][1] / 2) * (3.1415 / 2)))

    def getSort(self):
        '''
        调用IVqPSI里面的得分函数和精确值函数进行计算
        :return:
        '''
        q = self.q
        matrix = self.getQ()
        ScoreValue = []
        for i in range(len(matrix)):
            score= self.score(matrix[i], q)
            ScoreValue.append(score)
        return ScoreValue

    def getResult(self):
        temp=self.getSort()
        temp=[i/sum(temp) for i in temp]
        return temp


if __name__ == '__main__':
    a1 = [
        [([0.7, 0.8], [0.2, 0.3]), ([0.5, 0.6], [0.6, 0.7]), ([0.8, 0.9], [0.1, 0.2]), ([0.8, 0.95], [0.1, 0.2])],
        [([0.8, 0.9], [0.1, 0.2]), ([0.5, 0.55], [0.4, 0.5]), ([0.8, 0.9], [0.1, 0.15]), ([0.8, 0.95], [0.1, 0.2])],
        [([0.9, 0.95], [0.1, 0.2]), ([0.5, 0.6], [0.3, 0.4]), ([0.8, 0.85], [0.2, 0.3]), ([0.8, 0.9], [0.1, 0.2])],
        [([0.2, 0.3], [0.7, 0.8]), ([0.4, 0.5], [0.3, 0.4]), ([0.75, 0.8], [0.2, 0.3]), ([0.7, 0.8], [0.2, 0.3])],
        [([0.1, 0.2], [0.8, 0.9]), ([0.2, 0.3], [0.5, 0.6]), ([0.7, 0.85], [0.3, 0.4]), ([0.6, 0.7], [0.2, 0.3])]]
    weight = [0.242,0.356, 0.177, 0.225]
    type = [1, 1, 1, 0 ]
    CO = COPRAS(a1, weight,6)
    print(CO.getResult())

